package com.example.hanlp_service.utils;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLSentence;
import com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLWord;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment;
import com.hankcs.hanlp.seg.NShort.NShortSegment;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.IndexTokenizer;
import com.hankcs.hanlp.tokenizer.NLPTokenizer;
import com.example.hanlp_service.dto.DependencyWordDTO;
import com.example.hanlp_service.dto.NamedEntityDTO;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.logging.Logger;

public class HanLPUtil {

    private static final Logger logger = Logger.getLogger(HanLPUtil.class.getName());

    // 基础分词器（带地名、机构名识别）
    private static final Segment segment = HanLP.newSegment()
            .enablePlaceRecognize(true)
            .enableOrganizationRecognize(true);

    /**
     * 基础分词：返回 List<Term>，包含词语和词性等信息
     */
    public static List<Term> segment(String text) {
        return segment.seg(text);
    }

    /**
     * NLP 分词 + 词性标注（推荐使用这个作为高级分析接口）
     */
    public static List<Term> nlpSegment(String text) {
        return NLPTokenizer.segment(text);
    }

    /**
     * 返回纯字符串列表（只保留词语）
     */
    public static List<String> segmentWords(String text) {
        return segment(text).stream().map(term -> term.word).collect(Collectors.toList());
    }

    /**
     * 返回纯字符串列表（NLP 分析结果）
     */
    public static List<String> nlpSegmentWords(String text) {
        return nlpSegment(text).stream().map(term -> term.word).collect(Collectors.toList());
    }

    /**
     * 获取带词性标注的字符串（用于调试或输出）
     */
    public static String analyzeWithPos(String text) {
        return NLPTokenizer.analyze(text).translateLabels().toString();
    }

    /**
     * 提取文本摘要（抽取式）
     *
     * @param text             原始文本
     * @param maxSentenceCount 摘要句子数量
     * @return 摘要句子列表
     */
    public static List<String> extractSummary(String text, int maxSentenceCount) {
        return HanLP.extractSummary(text, maxSentenceCount);
    }

    public static List<String> extractSummarySorted(String text, int maxSentenceCount) {
    List<String> summary = HanLP.extractSummary(text, maxSentenceCount);

    // 去重 + 按照在原文中的出现位置排序
    return summary.stream()
        .distinct()
        .sorted(Comparator.comparingInt(text::indexOf))
        .collect(Collectors.toList());
}

    /**
     * 智能摘要提取：自动根据文本中识别出的命名实体数量决定摘要句数
     *
     * @param text 原始文本
     * @return 摘要句子列表
     */
    public static List<String> extractSummary(String text) {
        // 1. 提取命名实体
        List<NamedEntityDTO> entities = recognizeNamedEntities(text);

        // 2. 去重实体内容
        Set<String> uniqueEntities = entities.stream()
                .map(NamedEntityDTO::getEntity)
                .collect(Collectors.toSet());

        // 3. 设置 maxSentenceCount，默认值为实体数量（但不超过 5 句）
        // int maxSentenceCount = Math.min(uniqueEntities.size(), 5);
        int maxSentenceCount = uniqueEntities.size();

        // 4. 调用 HanLP 的摘要方法
        return extractSummarySorted(text, maxSentenceCount);
    }

    /**
     * 提取文本中的关键词性短语
     *
     * @param text           原始文本
     * @param maxPhraseCount 要提取的短语数量
     * @return 短语列表
     */
    public static List<String> extractPhrase(String text, int maxPhraseCount) {
        return HanLP.extractPhrase(text, maxPhraseCount);
    }

    /**
     * 智能短语提取：自动根据文本中识别出的命名实体数量决定智能短语句数
     *
     * @param text 原始文本
     * @return 短语列表
     */
    public static List<String> extractPhrase(String text) {
        // 1. 提取命名实体
        List<NamedEntityDTO> entities = recognizeNamedEntities(text);

        // 2. 去重实体内容
        Set<String> uniqueEntities = entities.stream()
                .map(NamedEntityDTO::getEntity)
                .collect(Collectors.toSet());

        // 3. 设置 maxSentenceCount，默认值为实体数量（但不超过 5 句）
        // int maxSentenceCount = Math.min(uniqueEntities.size(), 5);
        int maxSentenceCount = uniqueEntities.size();
        return extractPhrase(text, maxSentenceCount);
    }

    /**
     * 依存句法分析，返回简洁的 DTO 列表
     */
    public static List<DependencyWordDTO> dependencyParse(String text) {
        CoNLLSentence sentence = HanLP.parseDependency(text);
        List<DependencyWordDTO> result = new ArrayList<>();

        for (CoNLLWord word : sentence) {
            String headWord = word.HEAD == CoNLLWord.ROOT ? "ROOT" : word.HEAD.LEMMA;
            result.add(new DependencyWordDTO(word.LEMMA, headWord, word.DEPREL));
        }

        return result;
    }

    /**
     * 执行命名实体识别
     */
    public static List<NamedEntityDTO> recognizeNamedEntities(String text) {
        List<Term> termList = HanLP.segment(text);
        List<NamedEntityDTO> result = new ArrayList<>();

        for (Term term : termList) {
            String nature = term.nature.toString();
            logger.info("识别到实体：" + term.word + "，词性：" + nature);
            if (nature.equals("nr") || nature.equals("nr2") || nature.equals("ns") ||
                    nature.equals("nt") || nature.equals("nz")) { // 人名、地名、机构名、其他专有名词

                String entityType = "";
                if (nature.startsWith("nr"))
                    entityType = "PER"; // 人名
                else if (nature.equals("ns"))
                    entityType = "LOC"; // 地名
                else if (nature.equals("nt"))
                    entityType = "ORG"; // 机构名
                else
                    entityType = "MISC"; // 其他

                result.add(new NamedEntityDTO(
                        term.word,
                        entityType,
                        term.offset,
                        term.offset + term.word.length()));
            }
        }

        return result;
    }

    /**
     * 索引分词：适用于构建搜索引擎倒排索引场景
     */
    public static List<Term> indexSegment(String text) {
        return IndexTokenizer.segment(text);
    }

    /**
     * 返回索引分词结果的字符串列表（仅保留词语）
     */
    public static List<String> indexSegmentWords(String text) {
        return indexSegment(text).stream()
                .map(term -> term.word)
                .collect(Collectors.toList());
    }

    /**
     * 返回带偏移位置信息的索引分词结果（用于调试或输出）
     */
    public static List<String> indexSegmentWithPosition(String text) {
        return indexSegment(text).stream()
                .map(term -> term.word + " [" + term.offset + ":" + (term.offset + term.word.length()) + "]")
                .collect(Collectors.toList());
    }

    // N-最短路径分词器（关闭用户自定义词典，开启地名、机构名识别）
    private static final Segment nShortSegment = new NShortSegment()
            .enableCustomDictionary(false)
            .enablePlaceRecognize(true)
            .enableOrganizationRecognize(true);

    // 最短路径分词器（Dijkstra 算法）
    private static final Segment shortestSegment = new DijkstraSegment()
            .enableCustomDictionary(false)
            .enablePlaceRecognize(true)
            .enableOrganizationRecognize(true);

    /**
     * N-最短路径分词
     */
    public static List<Term> nShortSegment(String text) {
        return nShortSegment.seg(text);
    }

    /**
     * 最短路径分词（基于 Dijkstra 算法）
     */
    public static List<Term> shortestSegment(String text) {
        return shortestSegment.seg(text);
    }

    /**
     * 返回 N-最短路径分词结果的字符串列表（仅词语）
     */
    public static List<String> nShortSegmentWords(String text) {
        return nShortSegment(text).stream()
                .map(term -> term.word)
                .collect(Collectors.toList());
    }

    /**
     * 返回最短路径分词结果的字符串列表（仅词语）
     */
    public static List<String> shortestSegmentWords(String text) {
        return shortestSegment(text).stream()
                .map(term -> term.word)
                .collect(Collectors.toList());
    }

    /**
     * 返回带词性标注的 N-最短路径分词结果（用于调试或输出）
     */
    public static List<String> nShortSegmentWithPos(String text) {
        return nShortSegment(text).stream()
                .map(term -> term.toString())
                .collect(Collectors.toList());
    }

    /**
     * 返回带词性标注的最短路径分词结果（用于调试或输出）
     */
    public static List<String> shortestSegmentWithPos(String text) {
        return shortestSegment(text).stream()
                .map(term -> term.toString())
                .collect(Collectors.toList());
    }

    /**
     * 提取关键词列表
     *
     * @param text            原始文本
     * @param maxKeywordCount 要提取的关键词数量
     * @return 关键词字符串列表
     */
    public static List<String> extractKeyword(String text, int maxKeywordCount) {
        return HanLP.extractKeyword(text, maxKeywordCount);
    }

    /**
     * 智能关键词提取：根据命名实体数量自动决定提取数量
     *
     * @param text 原始文本
     * @return 关键词列表
     */
    public static List<String> extractKeyword(String text) {
        // 1. 提取命名实体
        List<NamedEntityDTO> entities = recognizeNamedEntities(text);

        // 2. 去重实体内容
        Set<String> uniqueEntities = entities.stream()
                .map(NamedEntityDTO::getEntity)
                .collect(Collectors.toSet());

        // 3. 设置 maxKeywordCount，默认值为实体数量（但不超过 10 个）
        int maxKeywordCount = Math.min(uniqueEntities.size(), 10);

        // 4. 调用 HanLP 的关键词提取方法
        return extractKeyword(text, maxKeywordCount);
    }
}